package com.ruoyi.framework.web.service;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.enums.DeviceCategory;
import com.ruoyi.common.enums.DeviceStatus;
import com.ruoyi.common.enums.RequestMapper;
import com.ruoyi.common.utils.RequestService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.fire.domain.DGatewayMessage;
import com.ruoyi.fire.domain.DWaterDeviceMessage;
import com.ruoyi.fire.domain.DWaterMessage;
import com.ruoyi.fire.domain.TDevice;
import com.ruoyi.fire.service.IDGatewayMessageService;
import com.ruoyi.fire.service.IDWaterDeviceMessageService;
import com.ruoyi.fire.service.IDWaterMessageService;
import com.ruoyi.fire.service.ITDeviceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class DynamicDataService {

    private final ITDeviceService deviceService;
    private final RequestService requestService;
    private final IDGatewayMessageService gatewayMessageService;
    private final IDWaterMessageService waterMessageService;
    private final IDWaterDeviceMessageService waterDeviceMessageService;


    // 静态常量提取，避免重复创建
    private static final List<String> GATEWAY_FAULT_TYPES = Arrays.asList("电源故障", "主电故障", "备电故障", "通讯故障", "故障");
    private static final List<String> GATEWAY_RESET_TYPES = Arrays.asList("复位", "故障恢复", "主电故障恢复", "备电故障恢复", "备电恢复", "恢复", "主电恢复");
    private static final List<String> GATEWAY_OTHER_TYPES = Arrays.asList("消音", "反馈", "消声");
    private static final List<String> GATEWAY_FIRE_TYPES = Arrays.asList("火警", "首次火警", "火灾报警", "火灾后续");

    // 水池/水箱
    private static final Set<String> WATER_POOL_TANK_TYPES = new HashSet<>(Arrays.asList("1", "4"));
    // 消火栓/喷淋
    private static final Set<String> WATER_SYSTEM_TYPES = new HashSet<>(Arrays.asList("2", "3"));
    // 消火栓
    private static final Set<String> HYDRANT_TYPES = new HashSet<>(Collections.singletonList("2"));
    // 喷淋
    private static final Set<String> SPRINKLER_TYPES = new HashSet<>(Collections.singletonList("3"));

    // 线程池配置
    private final ExecutorService executorService = new ThreadPoolExecutor(
            10, 50,
            60L, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(200),
            new ThreadFactory() {
                private final AtomicInteger threadNumber = new AtomicInteger(1);

                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "device-data-upload-" + threadNumber.getAndIncrement());
                    t.setDaemon(false);
                    return t;
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy()
    );


    public void dynamicDataUpload() {
        // 获取所有已经启用的设备
        List<TDevice> enableDevices = deviceService.enableDeviceWatchPushList(DeviceStatus.ENABLE, DeviceCategory.WATER);

        if (CollectionUtils.isEmpty(enableDevices)) {
            log.info("没有启用的设备");
            return;
        }

        enableDevices = enableDevices.stream().filter(item -> StringUtils.isNotEmpty(item.getDeviceId())).collect(Collectors.toList());

//        List<TDevice> uniqueDevices = enableDevices.stream()
//                .collect(Collectors.toMap(TDevice::getDeviceCode, device -> device, (existing, replacement) -> existing))
//                .values()
//                .stream()
//                .collect(Collectors.toList());

        // 使用并行处理提高并发性能
        List<CompletableFuture<Void>> futures = enableDevices.stream()
                .map(device -> CompletableFuture.runAsync(() -> processDeviceData(device), executorService))
                .collect(Collectors.toList());

        // 等待所有任务完成，并处理异常
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                .exceptionally(throwable -> {
                    log.error("处理设备数据时发生异常", throwable);
                    return null;
                }).join();
    }

    private void processDeviceData(TDevice device) {
        try {
//            if (DeviceCategory.GATEWAY.getCode().equals(device.getDeviceCategory())) {
//                // handleGatewayDevice(device);
//            } else {
            handleWaterDevice(device);
//            }
        } catch (Exception e) {
            log.error("处理设备 {} 数据异常: ", device.getDeviceCode(), e);
        }
    }

    private void handleGatewayDevice(TDevice device) {
        // 查询最近一次上报的数据
        DGatewayMessage dGatewayMessage = gatewayMessageService.selectLastOneByDeviceNo(device.getDeviceCode());

        if (StringUtils.isNull(dGatewayMessage)) return;

        // 网关协议
        Map<String, Object> params = new HashMap<>();
        // 设备id,创建设备时获得
        params.put("device_id", device.getDeviceId());

        // 报警状态，0-正常，1-报警  PS是火警是报警  其他为正常
        if (dGatewayMessage.getPS().equals("火警")) {
            params.put("alarm_status", 1);
        } else {
            params.put("alarm_status", 0);
        }

        // 故障状态，0-正常，1-故障 PS是故障是故障 其他为正常
        if (dGatewayMessage.getPS().equals("故障")) {
            params.put("abnormal_status", 1);
        } else {
            params.put("abnormal_status", 0);
        }

        // 屏蔽状态，0-正常，1-异常 都是正常
        params.put("shield_status", 0);
        // 事件发生时间，毫秒级时间戳，格式 1539776909000
        params.put("reported_at", System.currentTimeMillis());

        Map<String, Object> childData = new HashMap<>();

        String pt = dGatewayMessage.getPT();
        if (StringUtils.containsAny(GATEWAY_FAULT_TYPES, pt)) {
            childData.put("data_type_id", 15);
        } else if (StringUtils.containsAny(GATEWAY_RESET_TYPES, pt)) {
            childData.put("data_type_id", 16);
        } else if (StringUtils.containsAny(GATEWAY_OTHER_TYPES, pt)) {
            childData.put("data_type_id", 42);
        } else if (StringUtils.containsAny(GATEWAY_FIRE_TYPES, pt)) {
            childData.put("data_type_id", 84);
        }

        // data_value PT的值
        childData.put("data_value", dGatewayMessage.getPS());
        // alarm_status PS 为火警为报警 其他为正常
        if (dGatewayMessage.getPS().equals("火警")) {
            childData.put("alarm_status", 1);
        } else {
            childData.put("alarm_status", 0);
        }

        // abnormal_status PS为故障为故障 其他为正常
        if (dGatewayMessage.getPS().equals("故障")) {
            childData.put("abnormal_status", 1);
        } else {
            childData.put("abnormal_status", 0);
        }
        // threshold_const_value 阈值 0
        childData.put("threshold_const_value", "");
        childData.put("threshold_max_value", "");
        childData.put("threshold_min_value", "");

        List<Map<String, Object>> dataList = new ArrayList<>(1);
        dataList.add(childData);

        params.put("data", JSON.toJSONString(dataList));

        requestService.advancedRequest(RequestMapper.DYNAMIC_DATA_UPLOAD, params);
    }

    private void handleWaterDevice(TDevice device) {
        long currentTimeMillis = System.currentTimeMillis();
        // 水协议 判断是否超过六个半小时  超过不推送
        DWaterMessage waterMessage = waterMessageService.selectLastOneByDeviceNo(device.getDeviceCode());
        if (StringUtils.isNull(waterMessage)) return;

        if (CollectionUtils.isEmpty(waterMessage.getWaterDeviceMessages())) return;

        Map<String, Object> params = new HashMap<>();
        // 设备id,创建设备时获得
        params.put("device_id", device.getDeviceId());
        // 报警状态，0-正常，1-报警  都是正常
        params.put("alarm_status", 0);
        // 故障状态，0-正常，1-故障 都是正常
        params.put("abnormal_status", 0);
        // 屏蔽状态，0-正常，1-异常 都是正常
        params.put("shield_status", 0);
        // 事件发生时间，毫秒级时间戳，格式 1539776909000
        params.put("reported_at", currentTimeMillis);

        Map<String, Object> childData = new HashMap<>();

        String deviceName = device.getDeviceName();
        if (WATER_POOL_TANK_TYPES.contains(deviceName)) {
            // 水池水箱 单位 米
            childData.put("data_type_id", 2);
        } else if (WATER_SYSTEM_TYPES.contains(deviceName)) {
            // 消火栓/喷淋 单位 压力
            childData.put("data_type_id", 1);
        }

        processWaterDeviceData(childData, waterMessage, device);

        // 是否达到报警状态 都是0
        childData.put("alarm_status", 0);
        // 是否是异常状态 都是0
        childData.put("abnormal_status", 0);
        // data_model 0-水协议 1-网关协议
        childData.put("data_model", 0);

        List<Map<String, Object>> dataList = new ArrayList<>(1);
        dataList.add(childData);

        params.put("data", JSON.toJSONString(dataList));
        requestService.advancedRequest(RequestMapper.DYNAMIC_DATA_UPLOAD, params);
    }

    private void processWaterDeviceData(Map<String, Object> childData, DWaterMessage waterMessage, TDevice device) {
        String deviceName = device.getDeviceName();

        Optional<DWaterDeviceMessage> messageOpt = Optional.empty();
        if (WATER_POOL_TANK_TYPES.contains(deviceName)) {
            // 水池/水箱 数据项值 液位值 field4 A1
            messageOpt = waterMessage.getWaterDeviceMessages().stream()
                    .filter(item -> "A1".equals(item.getDevice()))
                    .findFirst();
        } else if (HYDRANT_TYPES.contains(deviceName)) {
            // 消火栓 数据项值 液位值 field4 A2
            messageOpt = waterMessage.getWaterDeviceMessages().stream()
                    .filter(item -> "A2".equals(item.getDevice()))
                    .findFirst();
        } else if (SPRINKLER_TYPES.contains(deviceName)) {
            // 喷淋 数据项值 液位值 field4 A3
            messageOpt = waterMessage.getWaterDeviceMessages().stream()
                    .filter(item -> "A3".equals(item.getDevice()))
                    .findFirst();
        }

        if (messageOpt.isPresent()) {
            DWaterDeviceMessage dWaterDeviceMessage = messageOpt.get();
            childData.put("data_value", dWaterDeviceMessage.getField4());

            if (StringUtils.isNotEmpty(device.getDeviceMax())) {
                // 阈值上限，data_model=0时 （模拟量）
                childData.put("threshold_max_value", device.getDeviceMax());
            } else {
                String fieldValue = dWaterDeviceMessage.getField6();
                // 如果field6以H开头，去掉H
                if (StringUtils.isNotEmpty(fieldValue) && fieldValue.startsWith("H")) {
                    fieldValue = fieldValue.substring(1);
                }
                childData.put("threshold_max_value", fieldValue);
            }

            if (StringUtils.isNotEmpty(device.getDeviceMin())) {
                // 阈值下限，data_model=0时 （模拟量）
                childData.put("threshold_min_value", device.getDeviceMin());
            } else {
                String fieldValue = dWaterDeviceMessage.getField5();
                // 如果field5以H开头，去掉H
                if (StringUtils.isNotEmpty(fieldValue) && fieldValue.startsWith("L")) {
                    fieldValue = fieldValue.substring(1);
                }
                childData.put("threshold_min_value", fieldValue);
            }
        }
    }
}
